---
title: condition
description: Condition实现了管程模型里的条件变量
---
Java 语言内置的管程里只有一个条件变量，而 Lock&Condition 实现的管程是支持多个条件变量。支持多个条件变量能够让并发程序可读性更好，实现起来更容易。

例如一个阻塞队列，就需要两个条件变量。
## 如何利用两个条件变量快速实现阻塞队列
一个阻塞队列，需要两个条件变量，一个是队列不空（队列为空不允许出队），另一个是队列不满（队列满了不允许入队）。相关的代码如下：

```java
public class BlockQueue<T>{
    final Lock lock = new ReentrantLock();
    //条件变量： 队列不满
    final Condition notFull = lock.newCondition();
    //条件变量：队列不空
    final Condition notEmpty = lock.newCondition();
    //入队
    void enq(T t){
        lock.lock();
        try{
            while(队列已满){
                //等待队列不满
                notFull.await();
            }
            //入队
            //入队后，通知可出队
            notEmpty.singal();
        }fianlly{
            lock.unlock();
        }
    }
    void deq(){
        lock.lock();
        try{
            while(队列为空){
                //等待队列不空
                notEmpty.await();
            }
            //出队
            //出队后，通知可入队
            notFull.signal();
        }finally{
            lock.unlock();
        }
    }
}
```
Lock 和 Condition 实现的管程，线程等待和通知需要调用** await()、signal()、signalAll()**,它们的语义和 wait()、notify()、notifyAll() 是相同的。


## 同步和异步
**同步和异步的区别通俗点来讲就是调用方是否需要等待结果，如果需要等待结果，就是同步；如果不需要等待结果，就是异步。**

同步，是Java 代码的默认处理方式。如果你想让程序支持异步，可以通过以下两种方式实现：

1. 调用方创建一个子线程，在子线程中执行方法调用，这种调用称为异步调用；
2. 方法实现的时候，创建一个新的线程执行主要逻辑，主线程直接 return，这种方法我们一般称为异步方法。

## Dubbo 源码分析

在编程领域，异步场景有很多，比如 TCP 协议本身就是异步的。还有就是工作中经常用到的 RPC 调用， 在 TCP 层面，发送完 RPC 请求后，线程是不会等待 RPC 的响应结果的。但 RPC 调用大多数都是同步的,这是因为框架做了异步转同步的事情。

RPC 其实就是发送 RPC 请求，之后通过调用 get() 方法等待 RPC 返回结果。
```java
public class DubboInvoker{
    Result doInvoke(Invoke inv){
        return currentClient.request(inv,timeout).get();
    }
}
```
当 RPC 返回结果之前，阻塞调用线程，让调用线程等待；当 RPC 返回结果后，唤醒调用线程，让调用线程重新执行。这就是经典的等待——通知机制。
```java
    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();

    //调用方通过该方法等待结果
    public Object get(int timeout) {
        long startTime = System.nanoTime();
        lock.lock();
        try {
            while (!isDone()) {
                done.await(timeout);
                long cur = System.nanoTime();
                if (isDone() || cur - startTime > timeout) {
                    break;
                }
            }
        } finally {
            lock.unlock();
        }
        if (!isDone()) {
            throw new TimeoutException();
        }
        return returnFromResponse();
    }

    //RPC 结果是否已返回
    private boolean isDone() {
        return response != null;
    }

    //RPC 返回结果时调用该方法
    private void doReceived(Response res) {
        lock.lock();
        try {
            response = res;
            if (done != null) {
                done.signal();
            }
        } finally {
            lock.unlock();
        }
    }
```
这里的每个 request 对应一个线程，并没有用到共享的资源，加锁只是因为利用管程实现线程的阻塞和唤醒。

while 条件是编程范式。
